<template>
  <div id="pdg6-container" class="relative" style="height: 100%">
    <div v-if="!showData" class="absolute top-50% left-50% text-[#666] text-center"
      style="transform: translate(-50%, -50%)">
      {{ showText }}
    </div>
  </div>
</template>

<script setup lang="ts">
import G6 from "@antv/g6";

const props = defineProps({
  effect: {
    type: Number,
  }
})
const emit = defineEmits(['nodeClick', 'defaultEcharts'])

let data = {}

function flattenData(data) {
  const flattenedData = [];

  function traverse(node, parentNode) {
    const flattenedNode = {
      id: node.mbId,
      name: node.mbmc,
      mblx: node.mblx,
      kw: node.kw,
      kwh: node.kwh,
    };
    flattenedData.push(flattenedNode);

    if (node.childList && node.childList.length > 0) {
      for (let i = 0; i < node.childList.length; i++) {
        traverse(node.childList[i], node);
      }
    }
  }

  traverse(data, null);

  return flattenedData;
}

function generateConnections(data) {
  const connections = [];

  function traverse(node, parentNode) {
    if (parentNode) {
      const connection = { source: parentNode.mbId, target: node.mbId };
      connections.push(connection);
    }

    if (node.childList && node.childList.length > 0) {
      for (let i = 0; i < node.childList.length; i++) {
        traverse(node.childList[i], node);
      }
    }
  }

  traverse(data, null);

  return connections;
}

function mergeDataAndConnections(data) {
  const filteredData = [];
  const encounteredIds = new Set();
  for (const item of flattenData(data)) {
    const itemId = item.id;
    if (!encounteredIds.has(itemId)) {
      encounteredIds.add(itemId);
      filteredData.push(item);
    }
  }

  const connections = generateConnections(data);

  return {
    nodes: filteredData,
    edges: connections,
  };
}

let graph: any = null
const showData = ref(false)
const showText = ref('加载中...')
function loadData() {
  if (graph) {
    showData.value = false
    graph.destroy()
  }

  queryDlYztInfo()
    .then((res: any) => {
      res.label = res.mbmc
      res.width = 240
      res.color = '#0F86E8'
      res.children = res.childList
      res.childList.forEach((item: any) => {
        item.label = item.mbmc
        item.width = 80
        item.color = '#DCEEF9'
        item.children = item.childList
        item.childList &&
          item.childList.forEach((bdz: any) => {
            bdz.label = bdz.mbmc
            bdz.width = 140
            bdz.color = '#fff'
            bdz.children = bdz.childList
            bdz.childList &&
              bdz.childList.forEach((jcdw: any) => {
                jcdw.label = jcdw.mbmc
                jcdw.width = 60
                jcdw.color = '#fff'
              })
          })
      })
      showData.value = true

      emit('defaultEcharts', res.children[0])

      data = mergeDataAndConnections(res);

      initPDG6()
    })
    .catch(() => {
      showText.value = '加载失败'
    })
}
loadData()

defineExpose({
  loadData,
  showData
})

function initPDG6() {
  G6.registerNode(
    "dom-node",
    {
      drawShape(cfg, group) {
        let rect;

        //节点为第一层
        if (cfg.id === "1") {
          const w = 340;
          const h = 40;
          rect = group.addShape("dom", {
            attrs: {
              width: w,
              height: h,
              html: `
             <div style="width: ${w - 5}px; height: ${h - 5
                }px; line-height: ${h - 5
                }px; background-color: #0F86E8; border-radius: 10px; text-align: center;">
            <span style="font-size: 18px; color: #fff">${cfg.name}</span>
          </div>
          `,
            },
          });
        }
        //节点为二层
        else if (cfg.id !== "1" && !cfg.mblx) {
          const w = 200;
          const h = 40;
          rect = group.addShape("dom", {
            attrs: {
              width: w,
              height: h,
              html: `
        <div style="display: flex; align-items: center">
          <div style="width: ${w - 5}px; height: ${h - 5
                }px; line-height: ${h - 5
                }px; border: 1px solid #0F86E8; background-color: #DCEEF9; text-align: center; margin-right: 5px">
              <span style="font-size: 18px; color: #0F86E8">${cfg.name}</span>
             </div>
          <div>
                <div style="display: flex; align-items: center; width: 100px; height: 18px; background-color: #4FBFB9; border-radius: 9px; text-align: center; font-size: 12px; color: #fff; margin-bottom: 4px">
              <span title="${cfg.kw}" style="display: inline-block; flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; margin-left: 5px">${cfg.kw}</span>
              <span style="width: 30px; margin-right: 5px">KW</span>
            </div>
            <div style="display: flex; align-items: center; width: 100px; height: 18px; background-color: #4FBFB9; border-radius: 9px; text-align: center; font-size: 12px; color: #fff">
              <span title="${cfg.kwh}" style="display: inline-block; flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; margin-left: 5px">${cfg.kwh}</span>
              <span style="width: 30px; margin-right: 5px">KWH</span>
            </div>
         </div>
        </div>
          `,
            },
          });
        }
        //节点为第三层
        else {
          rect = group.addShape("dom", {
            attrs: {
              width: 140,
              height: 110,
              html: `
        <div id="${cfg.id}" class="dom-node" style="display: flex; flex-direction: column; align-items: center; cursor: pointer;">
          <div style="padding: 5px; border: 1px solid #0F86E8; text-align: center; margin-bottom: 10px">
              <span style="font-size: 14px; color: #0F86E8">${cfg.name}</span>
             </div>

          <div>
            <div style="display: flex; align-items: center; width: 120px; height: 18px; background-color: #4FBFB9; border-radius: 9px; text-align: center; font-size: 12px; color: #fff; margin-bottom: 4px">
              <span title="${cfg.kw}" style="display: inline-block; flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; margin-left: 5px">${cfg.kw}</span>
              <span style="width: 30px; margin-right: 5px">KW</span>
            </div>
            <div style="display: flex; align-items: center; width: 120px; height: 18px; background-color: #4FBFB9; border-radius: 9px; text-align: center; font-size: 12px; color: #fff">
              <span title="${cfg.kwh}" style="display: inline-block; flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; margin-left: 5px">${cfg.kwh}</span>
              <span style="width: 30px; margin-right: 5px">KWH</span>
            </div>
         </div>
        </div>
          `,
            },
          });
        }

        return rect;
      },
    },
    "single-node"
  );

  if (props.effect === 0) {
    G6.registerEdge('flow-line', {
      draw(cfg, group) {
        const startPoint = cfg.startPoint;
        const endPoint = cfg.endPoint;

        const { style } = cfg;
        const shape = group.addShape('path', {
          attrs: {
            stroke: style.stroke,
            endArrow: style.endArrow,
            path: [
              ['M', startPoint.x, startPoint.y],
              ['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
              ['L', endPoint.x, (startPoint.y + endPoint.y) / 2],
              ['L', endPoint.x, endPoint.y],
            ],
          },
        });

        return shape;
      },
    });
  } else if (props.effect === 1) {
    G6.registerEdge('flow-line', {
      draw(cfg, group) {
        const startPoint = cfg.startPoint;
        const endPoint = cfg.endPoint;

        const { style } = cfg;
        const shape = group.addShape('path', {
          attrs: {
            stroke: style.stroke,
            endArrow: style.endArrow,
            path: [
              ['M', startPoint.x, startPoint.y],
              ['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
              ['L', endPoint.x, (startPoint.y + endPoint.y) / 2],
              ['L', endPoint.x, endPoint.y],
            ],
          },
        });

        return shape;
      },
      afterDraw(cfg, group) {
        const shape = group.get('children')[0];
        const startPoint = shape.getPoint(0);

        const circle = group.addShape('circle', {
          attrs: {
            x: startPoint.x,
            y: startPoint.y,
            fill: '#1890ff',
            r: 3,
          },
          name: 'circle-shape',
        });

        circle.animate(
          (ratio) => {
            const tmpPoint = shape.getPoint(ratio);
            return {
              x: tmpPoint.x,
              y: tmpPoint.y,
            };
          },
          {
            repeat: true,
            duration: 3000,
          },
        );
      },
    });
  } else if (props.effect === 2) {
    const lineDash = [4, 2, 1, 2];
    G6.registerEdge('flow-line', {
      draw(cfg, group) {
        const startPoint = cfg.startPoint;
        const endPoint = cfg.endPoint;

        const { style } = cfg;
        const shape = group.addShape('path', {
          attrs: {
            stroke: style.stroke,
            endArrow: style.endArrow,
            path: [
              ['M', startPoint.x, startPoint.y],
              ['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
              ['L', endPoint.x, (startPoint.y + endPoint.y) / 2],
              ['L', endPoint.x, endPoint.y],
            ],
          },
        });

        return shape;
      },
      afterDraw(cfg, group) {
        const shape = group.get('children')[0];
        let index = 0;
        shape.animate(
          () => {
            index++;
            if (index > 9) {
              index = 0;
            }
            const res = {
              lineDash,
              lineDashOffset: -index,
            };
            return res;
          },
          {
            repeat: true,
            duration: 3000,
          },
        );
      },
    });
  }

  const container = document.getElementById("pdg6-container");
  const width = container.scrollWidth;
  const height = container.scrollHeight || 500;
  graph = new G6.Graph({
    container: "pdg6-container",
    width,
    height,
    layout: {
      type: "dagre",
      nodesepFunc: (d) => {
        return 90;
      },
      ranksep: 80,
      controlPoints: true,
    },
    defaultNode: {
      type: "dom-node",
    },
    defaultEdge: {
      type: 'flow-line',
      style: {
        stroke: '#3699FF',
      },
    },
    modes: {
      default: [
        "drag-canvas",
        "zoom-canvas",
      ],
    },
    renderer: "svg",
    fitView: true,
  });
  graph.data(data);
  graph.render();

  const bindClickListener = () => {
    const domNodes = document.getElementsByClassName('dom-node');
    for (let i = 0; i < domNodes.length; i++) {
      const dom = domNodes[i];
      dom.addEventListener('click', (e) => {
        data.nodes.forEach(item => {
          if (item.id === dom.id) {
            emit('nodeClick', { mbId: item.id, ...item })
          }
        })
      });
    }
  };

  graph.on('afterupdateitem', (e) => {
    bindClickListener();
  });
  graph.on('afterrender', (e) => {
    bindClickListener();
  });
}

onUnmounted(() => {
  if (graph) {
    graph.destroy()
  }
})
</script>

<style scoped>
</style>
